package org.jeecg.xs.util;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;


@Component
@Slf4j
public class OrderUtil {
    /**
     * 获取新订单号
     * @return
     */
	private static long workerId;

	@Value("${snowflake.worker-id}")
	private void setWorkerId(long workerId) {
		OrderUtil.workerId = workerId;
	}
	private static long datacenterId = 0;
	private static long sequence = 0L;

	private static long twepoch = 1288834974657L;

	private static long workerIdBits = 8L;
	private static long datacenterIdBits = 2L;
	private static long maxWorkerId = -1L ^ (-1L << workerIdBits);
	private static long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
	private static long sequenceBits = 12L;
	private static long workerIdShift = sequenceBits;
	private static long datacenterIdShift = sequenceBits + workerIdBits;
	private static long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
	private static long sequenceMask = -1L ^ (-1L << sequenceBits);

	private static long lastTimestamp = -1L;

	public static synchronized String getNewOrderNo() {
		long timestamp = timeGen();

		if (timestamp < lastTimestamp) {
			long delay = lastTimestamp - timestamp;
			throw new RuntimeException(String.format("服务器时间异常 时差：%d 毫秒", delay));
		}

		if (lastTimestamp == timestamp) {
			sequence = (sequence + 1) & sequenceMask;
			if (sequence == 0) {
				timestamp = tilNextMillis(lastTimestamp);
			}
		} else {
			sequence = 0L;
		}

		lastTimestamp = timestamp;

		return (((timestamp - twepoch) << timestampLeftShift) | (datacenterId << datacenterIdShift)
				| (workerId << workerIdShift) | sequence) + "";
	}

	/**
	 * 获取商品编号
	 * @return
	 */
	public static synchronized String getProductNo() {

		return "P"+getNewOrderNo();
	}

	protected static long tilNextMillis(long lastTimestamp) {
		long timestamp = timeGen();
		while (timestamp <= lastTimestamp) {
			timestamp = timeGen();
		}
		return timestamp;
	}

	protected static long timeGen() {
		return System.currentTimeMillis();
	}

}
